#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import logging
import wsgiref.handlers
from apptwitter import AppEngineTwitter
from django.utils import simplejson
from google.appengine.ext import webapp
from google.appengine.api import xmpp
from google.appengine.ext import db
from db_service import DBService
import xml.sax.saxutils
import config

OAUTH_KEY = config.OAUTH_KEY
OAUTH_SECRET = config.OAUTH_SECRET
BOT=config.ACCOUNT

HEADER='''
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>TwiTalker - Tweet it Easy with your Gtalk</title>
<link href="/img/favicon.ico" rel="shortcut icon" type="image/x-icon">
<link rel="stylesheet" type="text/css" media="screen" href="/css/style.css" /> 
</head>

<body>
<div id="top"></div>
<div id="header">
<div id="header_box"><img style="float:left" src="img/logo.png" />
<ul id="navCircle">
<!-- CSS Tabs -->
<li><a href="/">首页</a></li>
<li><a href="faq">帮助</a></li>
<li><a href="about">关于</a></li>
<li><a href="http://twitalkerblog.appspot.com">BLOG</a></li>
</ul>
</div>
<div class="clean"></div>
</div>
<div id="header_bottom"></div>
'''

JS='''
<SCRIPT LANGUAGE="JavaScript">
<!-- Begin
function copyit(theField) {
var tempval=eval("document."+theField)
tempval.focus()
tempval.select()
therange=tempval.createTextRange()
therange.execCommand("Copy")
}
//  End -->
</script>
'''

FOOTER='''
<div id="footer">
Copyright (C) 2009-2010 TwiTalker | <a href="http://www.kavingray.com">Kavin</a> | <a href="http://code.google.com/p/twitalker/">Open Source</a> | Powered by <a href="http://code.google.com/appengine/">Google appengine</a>
</div>
</body>
</html>
'''

 
 
class InitHandler(webapp.RequestHandler):
 
    def get(self):
      
        twitter = AppEngineTwitter()
        twitter.set_oauth(key=OAUTH_KEY, secret=OAUTH_SECRET)
        req_info = twitter.prepare_oauth_login()
        
        OAuthRequestToken(token=req_info['oauth_token'],
                          secret=req_info['oauth_token_secret']).put()
        
        # get the oauth url
        oauth_url=xml.sax.saxutils.escape(req_info['url'], {'"': "&quot;"})
        # oauth_url=h(req_info['url'])


        content='''
        <div id="container">
        <div id="intro"><h2>Tweet  It  Easy</h2>
        <p>TwiTalker是一款第三方应用，提供推特Gtalk机器人服务，通过添加TwiTalker在Gtalk上的帐号您可以方便地在Gtalk上更新自己的推特和接收好友消息。如果第一次使用TwiTalker请<a href="%s">登陆</a>验证获取验证码和密钥(<a href="faq">如何获取</a>)，以便Gtalk绑定推特帐号，具体验证绑定过程详见帮助。欢迎在推特上Follow <a href="https://twitter.com/Twi_Talker">@Twi_Talker</a>以获取最新消息和更新。<br /></p>
        <h2>TwiTalker 功能格式</h2>
        <p>查看帮助: -help</p>
        <p>绑定用户：-v 空格 认证码 空格 密钥 </p>
        <p>删除绑定：-remove</p>
        <p>开启完全消息接收(接收好友消息和私信)：-on</p>
        <p>开启自我消息接收(只接受好友@我消息和私信)：-self</p>
        <p>完全关闭消息接收(屏蔽所有消息)：-off</p>
        <p>查看最近回复：-@</p>
        <p>查看最近私信：-d</p>
        <p><a href="faq">更多功能请参考帮助....</a></p>
        </div>

        <div id="step">
        <h2>OAuth验证(需翻墙)</h2>
        <a href="%s"><img style="margin-bottom:0px" src="img/login.png" /></a><br />
        <h2>工作原理</h2>
        <p>TwiTalker利用Google appengine为平台架设，通过OAuth验证，用户不需提供密码就可以把自己的Gtalk帐号和推特绑定在一起，这样就可以通过Gtalk更新自己的推特消息，由于考虑服务器负载问题，每个TwiTalker机器人帐号好友上限是250人。TwiTalker已经开源，如果您对TwiTalker的原理和开发感兴趣，欢迎查看项目主页或联系开发者<a href="https://twitter.com/kavin_gray">@Kavin_Gray</a></p>
        <img style="margin-bottom:0px" src="img/tie.png" />
        </div>
        <div class="clean"></div>
        </div>
        '''%(oauth_url,oauth_url)
    
        # initing the pages    
        self.response.out.write(HEADER)    
        self.response.out.write(content)
        self.response.out.write(FOOTER)


 
class FaqHandler(webapp.RequestHandler):
 
    def get(self):
      
        content='''
        <div id="container">
        <div id="content">
        <h2>FAQ目录</h2>
        <p>
        <a href="#Q1">1. 怎样才能绑定使用TwiTalker？</a><br />
        <a href="#Q2">2. TwiTalker有哪些功能？</a><br />
        <a href="#Q3">3. 什么是self(自我消息接收)模式？</a><br />
        <a href="#Q4">4. 什么是live(直播)模式？</a><br />
        <a href="#Q5">5. 什么是消息附加ID模式？</a><br />
        <a href="#Q6">6. 如何回复某条消息？</a><br />
        <a href="#Q7">7. 如何删除自己的消息？</a><br />
        <a href="#Q8">8. 什么是OAuth验证，安不安全？</a><br />
        <a href="#Q9">9. 为什么要等好一会才接收到好友消息？</a><br />
        <a href="#Q10">10. 怎样才能解除TwiTalker绑定？</a><br />
        <a href="#other">11. 还有其他问题</a><br />
        </p>
        <h2><a name="Q1">怎样才能绑定使用TwiTalker？</a></h2>
        <p>首先你必须有一个推特(Twitter)帐号，一个GTalk帐号。如果你是第一次使用，必须通过OAuth验证绑定帐号，简单三步即可完成：<br />
        第一步：从这里登陆推特(Twitter)通过OAuth验证获取验证码和密钥，需要翻墙<br />
        <img src="img/s1.jpg" /><br /><br />
        <img src="img/s2.jpg" /><br /><br />
        第二步：然后根据提示在Gtalk上添加指定的TwiTalker帐号为好友<br />
        <img src="img/s3.jpg" /><br /><br />
        第三步：最后给添加的TwiTalker机器人发送绑定命令，格式是 <b>-v 空格 验证码 空格 密钥</b> 即可完成绑定。<br />
        <img src="img/s4.jpg" /><br /><br />
        绑定成功后你就可以方便地使用GTalk更新自己的推特信息
        </p>

        <h2><a name="Q2">TwiTalker有哪些功能？</a></h2>
        <p>在GTalk上给TwiTalker输入命令就可启动相应的功能，下面列出TwiTalker目前实现的功能极其命令格式<br />
        <b>TwiTalker设置功能:</b><br />
        查看帮助: <b>-help</b><br />
        查看所有帮助: <b>-all</b><br />
        绑定用户：<b>-v 认证码  密钥</b><br />
        删除绑定：<b>-remove</b><br />
        个人TwiTalker信息：<b>-status</b> 或 <b>-st</b><br />
        附加工具：<b>-tool</b><br />
        开启完全消息接收(接收好友消息和私信)：<b>-on</b><br />
        开启自我消息接收(只接受好友@我消息和私信)：<b>-self</b><br />
        直播模式消息接收(接收默认群组消息)：<b>-live</b><br />
        设置直播模式默认群组：<b>-live 群组创建者用户名 群组名或群组ID号</b> (例:-live kavin_gray test)<br />
        完全关闭消息接收(屏蔽所有消息)：<b>-off</b><br />
        设置消息接收刷新时间：<b>-time 分钟数</b></b>(只能取1到5的整数)<br />
        <b>推特操作功能:</b><br />
        查看收藏：<b>-fav 页数</b> (页数可省略，页数之前要带字母P，如-fav p2)<br />
        查看私信：<b>-d 页数</b> (页数可省略，页数之前要带字母P，如-d p2)<br />
        @我消息：<b>-@ 页数</b> (页数可省略，页数之前要带字母P，如-@ p2)<br />
        好友RT消息：<b>-rt 页数</b> (页数可省略，页数之前要带字母P，如-rt p2)<br />
        自己发表的消息：<b>-me 页数</b> (页数可省略，页数之前要带字母P，如-me p2)<br />
        最近好友更新：<b>-home 页数</b> 或 <b>-ho 页数</b> (页数可省略，页数之前要带字母P，如-ho p2)<br />
        查看用户更新：<b>-tl 用户名 页数</b> (页数可省略，页数之前要带字母P，如-tl twi_talker p2)<br />
        搜索消息：<b>-s 关键词 页数</b> (页数可省略，页数之前要带字母P，如-s twitalker p1)<br />
        查看群组更新：<b>-list 群组创建者 群组名或群组ID 页数</b> 或 <b>-lt 群组创建者 群组名或群组ID 页数</b> (页数可省略，页数之前要带字母P)<br />
        你创建的群组：<b>-mlist next/pre</b> 或 <b>-mt next/pre</b> (next或pre可省略，如需翻页则用next或pre分别表示下页或上页)<br />
        你关注的群组：<b>-list next/pre</b> 或 <b>-lt next/pre</b> (next或pre可省略，如需翻页则用next或pre分别表示下页或上页)<br />
        关注你的群组：<b>-listed next/pre</b> 或 <b>-ld next/pre</b> (next或pre可省略，如需翻页则用next或pre分别表示下页或上页)<br />
        回复特定消息：<b>-@ 消息id号  回复内容</b><br />
        查看特定消息：<b>-msg 消息id号</b><br />
        删除最近发布的一条消息：<b>-del</b><br />
        删除自己的消息：<b>-del 消息id号</b><br />
        给某人发送私信：<b>-d 用户名 私信内容</b><br />
        消息收藏：<b>-fav 消息id号</b><br />
        取消消息收藏：<b>-unfav 消息id号</b><br />
        消息RT：<b>-rt 消息id号 附加消息</b>(附加消息可省略)<br />
        官方RT：<b>-r 消息id号</b><br />
        查看某人信息：<b>-status 用户名</b> 或 <b>-st 用户名</b><br />
        关注某人：<b>-follow 用户名</b> 或 <b>-fo 用户名</b><br />
        取消关注某人：<b>-unfollow 用户名</b> 或 <b>-uf 用户名</b><br />
        某人是否关注你：<b>-if 用户名</b><br />
        拉黑某人：<b>-block 用户名</b><br />
        开启消息附加ID模式：<b>-idon</b><br />
        关闭消息附加ID模式：<b>-idoff</b><br />
        查看绑定帐号列表: <b>-bind</b><br />
        增加新绑定帐号：<b>-bind 认证码  密钥</b><br />
        取消指定帐号绑定：<b>-unbind 帐号名</b><br />
         帐号切换：<b>-switch 帐号名</b> 或 <b>-sw 帐号名</b><br />
        </p>

        <h2><a name="Q3">什么是self(自我消息接收)模式？</a></h2>
        <p>TwiTalker的self自我状态，即是自动接收好友@我的消息和私信，屏蔽其他消息，这种状态适用于好友数比较多的或喜欢安静却怕错过回复信息的用户，输入-self就可以启动这种功能。</p>

        <h2><a name="Q4">什么是live(直播)模式？</a></h2>
        <p>Live模式是自动接收某群组消息的模式，第一次使用-live模式需要设置默认接收群组。
        设置命令: -live 群组创建者 群组名或ID，比如Twi_Talker创建了一个群组Test，而你想自动接收那个群组的消息，则只要设置-Live twi_talker test。
        这样设置后，以后如果你处在别的接收模式，而要转到live模式接收这个群组信息，则只要输入-live命令即可 </p>

        <h2><a name="Q5">什么是消息附加ID模式？</a></h2>
        <p>这是主要为在Gtalk上RT和收藏而设立的一个功能，输入-idon启动该模式，-idoff关闭，启动消息附加ID的用户所接收的消息末尾都会附加那条消息的ID号。</p>


        <h2><a name="Q6">如何回复某条消息？</a></h2>
        <p>一般可以用官方的 @用户名 空格 内容 来回复某人，但如果你要回复某条特定消息，也可输入<b>-@ 空格 消息id号 空格 回复内容</b>来进行回复。
        如果你想查看某条消息是答复那条推的，输入-msg 空格 消息ID号 即可查看，如果不是很清楚，
        这里有<a href="http://www.mobypicture.com/user/kavin_gray/view/5844762/sizes/full">图文说明</a></p>

        <h2><a name="Q7">如何删除自己的消息？</a></h2>
        <p>首先输入<b>-me</b>查看自己最近10条消息，每条消息后面都有带一个消息ID号，如果想删除某条消息，输入<b>-del 空格 消息id号</b> 即可。</p>

        <h2><a name="Q8">什么是OAuth验证，安不安全？</a></h2>
        <p>OAuth协议授权验证不会使第三方触及到用户的帐号信息(如用户名与密码)，即第三方应用如TwiTalker在不用触及用户的密码的前提下，
        就可以申请获得该用户资源的授权，用户可以授权该应用使用自己的信息，如更新推特，查看好友动态；当然，用户也可以随时中止授权给第三方。
        所以，OAuth协议下用户永远掌握着主动权，也是目前非常安全的授权协议之一，需要注意的是，在验证后获得的验证码和密钥是TwiTalker唯一能和你推特帐号关联的凭据，所以请妥善保管好它们</p>

        <h2><a name="Q9">为什么要等好一会才接收到好友消息？</a></h2>
        <p>TwiTalker默认是每两分钟程序才接收一次好友信息更新，并将这些信息在GTalk上返送给你。你可以输入-time+空格+分钟数(只能取1到5的整数) 来对接收时间进行调整，
        需要注意的是，由于Twitter api的限制，每一次最多只能返回最近的20条消息，所以如果你好友数多或者好友更新数多的话，
        设置过长的刷新时间可能会无法获取一些消息。刷新时间最短可以设置为一分钟，最长是五分钟，我们推荐的是两分钟刷新一次。</p>

        <h2><a name="Q10">怎样才能解除TwiTalker绑定？</a></h2>
        <p>给TwiTalker机器人上输入"-remove"命令即可解除绑定，如果下次您还要使用TwiTalker，则必须重新进行认证绑定</p>


        <h2><a name="other" id"other">还有其他问题</a></h2>
        <p>请在推特上反馈给<a href="https://twitter.com/twi_talker">@Twi_Talker</a> 或者直接联系开发者<a href="http://kavingray.com">Kavin</a></p>
        </div>
        </div>'''
    
        self.response.out.write(HEADER)    
        self.response.out.write(content)
        self.response.out.write(FOOTER)



class AboutHandler(webapp.RequestHandler):
 
    def get(self):
        self.response.out.write(HEADER)
        con='''
      <div id="container">
<div id="content">
<h2>关于TwiTalker</h2>
<p>TwiTalker 是一款基于GAE的twitter gtalk机器人，于2009年9月开始运行。
TwiTalker旨在为广大用户特别是中文用户提供一种方便快捷使用Twitter的方法，此项目已经完全开源，欢迎为TwiTalker作出改进或扩展新功能。
<br />如果你对TwiTalker的原理感兴趣，也可以看看作者写的<a href="http://www.kavingray.com/blog/twitalker/">介绍文章</a>。
或者访问TwiTalker的<a href="http://code.google.com/p/twitalker/">项目地址</a></p>
</div>
</div>
      '''
        self.response.out.write(con)
        self.response.out.write(FOOTER)      
      
    

        
        
class CallbackHandler(webapp.RequestHandler):
 
    def get(self):
        
        twitter = AppEngineTwitter()
        twitter.set_oauth(OAUTH_KEY, OAUTH_SECRET)
        req_token = self.request.get('oauth_token')
 
        query = OAuthRequestToken.all()
        query.filter('token = ', req_token)
        req_tokens = query.fetch(1)
 
        acc_token = twitter.exchange_oauth_tokens(req_token, req_tokens[0].secret)
 
        if (twitter.verify()==200):
            name = simplejson.loads(twitter.last_response.content)['screen_name']
            self.response.out.write(HEADER)
            self.response.out.write(JS)
            con_begin='''
            <div id="container">
            <div id="content">
            <h2>验证成功:)</h2>
            <P>恭喜你，%s，你已经成功授权TwiTalker并获取验证码和密钥，请<strong>务必首先保管好它们</strong>，并按步骤在Gtalk上添加TwiTalker帐号并完成绑定</p>'''%(name.encode("utf-8"))
            self.response.out.write(con_begin)
            self.response.out.write("验证码: ")
            self.response.out.write(acc_token['oauth_token'])
            self.response.out.write("<br />密钥: ")
            self.response.out.write(acc_token['oauth_token_secret'])
            con_copy='''
            <form name="it">
            <textarea name="select1" rows="2" cols="120">-v '''+acc_token['oauth_token']+" "+acc_token['oauth_token_secret']+'''</textarea>
            <input onclick="copyit('it.select1')" type="button" value="复制绑定信息" name="cpy"></input>
            </form>
            '''
            self.response.out.write(con_copy)
            db_ser = DBService()            
            db_ser.setQuery('TwiCount')
            twiNum=db_ser.getQuery()
            num=twiNum.count()
            if(num<250):
                con_foot='<p>下一步: 推荐在GTalk添加'+ BOT +'为好友，并向该帐号发送以下格式绑定信息完成绑定:<br /><b>-v 空格 验证码 空格 密钥</b> (也可以直接复制框中信息并向机器人帐号发送)'+'</p>'
            else:
                con_foot='<p>目前没有可用机器人</p> '
        
            self.response.out.write(con_foot)
            self.response.out.write('<p>如果你对验证过程仍有疑问，请参考<a href="faq">帮助页面</a></p>')
            
            self.response.out.write(FOOTER)



    
#Model(s)
 
class OAuthRequestToken(db.Model):
    token = db.StringProperty()
    secret = db.StringProperty() 
 
 
 
logging.getLogger()
routing = [('/', InitHandler),
           ('/faq', FaqHandler),
           ('/about', AboutHandler),
           ('/oauth', CallbackHandler)]
application = webapp.WSGIApplication(routing, debug=False)
wsgiref.handlers.CGIHandler().run(application)
